#ifndef EVM_HTTP_ROUTING_H
#define EVM_HTTP_ROUTING_H

#include <vector>
#include <string>
#include <unordered_map>
#include <functional>
#include <memory>

#include <regex>

#include "request.h"
#include "response.h"
#include "util.h"


namespace evm {
    namespace http {


        enum VarType {
            STR,
            UUID
        };

        using namespace std;
        using PathParas = unordered_map<string, string>;
        using Callback = function<Response (Request&)>;

        class Request;
        class Response;

        class Rule {
            friend class Router;

        public:
            Rule(const string &rule, HTTPMethod method=GET);
            
            size_t match(const string &url) const;

            bool match(const string &url, PathParas &paras) const;

            void operator()(Callback cb) {
                callback_ = std::move(cb);
            }

            string rule_;
            HTTPMethod method_;

            regex pattern_;
//            vector<pair<string, VarType>> vars_;
            vector<pair<string, string>> vars_;

            Callback callback_;
        };

        inline bool operator==(const Rule& lhs, const Rule& rhs) {
            return lhs.rule_ == rhs.rule_ && lhs.method_ == rhs.method_;
        }

        inline bool operator!=(const Rule& lhs, const Rule& rhs) {
            return lhs.rule_ != rhs.rule_ || lhs.method_ != rhs.method_;
        }

        class Router {
        public:
            Rule& operator()(const string& rule, HTTPMethod method=GET);
            
            Response route(const string& url, Request& req);

            struct RuleTuple {
                string url;
                HTTPMethod method;
                Callback callback;
            };

            void add(std::initializer_list<RuleTuple> rules);

        private:
            vector<Rule> rules_;
        };

    }
}

#endif //EVM_HTTP_ROUTING_H
